package org.simple_framework.util;

import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLDecoder;
import java.util.HashSet;
import java.util.Set;

/**
 * @author wxc
 * @date 2021年10月06日 22:04
 */
@Slf4j
public class LoadBeanUtil {

    public static final String CLASS_SUFFIX = ".class";

    private LoadBeanUtil() {
    }

    public static Set<Class<?>> extractPackageClass(String packageName) {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        URL url = classLoader.getResource(packageName.replace(".", "/"));
        Set<Class<?>> classes = null;
        if (url == null) {
            log.warn("unable to retrieve anything from package: " + packageName);
        } else {
            String s = null;
            try {
                s = URLDecoder.decode(url.getPath(), "utf8");
            } catch (UnsupportedEncodingException e) {
                log.error("{}", e.toString());
                throw new RuntimeException(e);
            }
            File file = new File(s);
            classes = new HashSet<>();
            extractClassFile(classes, file, packageName);
        }
        return classes;
    }

    private static void extractClassFile(Set<Class<?>> classes, File file, String packageName) {
        if (file.isFile() && file.getPath().endsWith(CLASS_SUFFIX)) {
            addToClassSet(classes, file.getPath(), packageName);
        } else {
            File[] files = file.listFiles();
            if (files != null && files.length > 0) {
                for (File childFile : files) {
                    extractClassFile(classes, childFile, packageName);
                }
            }
        }
    }

    /**
     * @param classes     存储Class类的Set
     * @param fileName    文件名 C:\Users\WXC\Desktop\编程\simple-framework\target\classes\com\wxc\controller\HelloController.class
     * @param packageName com.wxc.Controller
     * @date 2021-10-06 22:56
     */
    private static void addToClassSet(Set<Class<?>> classes, String fileName, String packageName) {
        String className = fileNameToClassName(fileName, packageName);
        try {
            Class<?> clazz = Class.forName(className);
            classes.add(clazz);
        } catch (ClassNotFoundException e) {
            log.error("class generator fail {}", e.toString());
            throw new RuntimeException(e);
        }

    }

    /**
     * @param fileName C:\Users\WXC\Desktop\编程\simple-framework\target\classes\com\wxc\controller\HelloController.class
     * @return java.lang.String
     * @date 2021-10-07 8:50
     */
    private static String fileNameToClassName(String fileName, String packageName) {
        fileName = fileName.replace(File.separator, ".");
        String className = fileName.substring(fileName.lastIndexOf(packageName));
        className = className.substring(0, className.lastIndexOf("."));

        System.out.println(className);
        return className;
    }

    public static void main(String[] args) {
        extractPackageClass("com.wxc.controller");
    }

    public static Object newInstance(Class<?> clazz) {
        try {
            Constructor<?> constructor = clazz.getDeclaredConstructor();
            return constructor.newInstance();
        } catch (Exception e) {
            log.error("newInstance fail", e);
            throw new RuntimeException(e);
        }
    }

    public static void fieldInject(Field field, Object o, Object value, boolean accessible) {
        field.setAccessible(accessible);
        try {
            field.set(o, value);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
